/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月28日
 */
package com.massyframework.beanskin.runtime.framework;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.massyframework.beanskin.ModuleListener;
import com.massyframework.beanskin.ModuleRepository;
import com.massyframework.beanskin.ModuleRuntimeException;
import com.massyframework.beanskin.SimpleModuleIdentifier;
import com.massyframework.beanskin.customer.Customer;
import com.massyframework.beanskin.framework.Framework;
import com.massyframework.beanskin.framework.FrameworkConfig;
import com.massyframework.beanskin.framework.FrameworkFactory;
import com.massyframework.beanskin.framework.FrameworkListener;
import com.massyframework.beanskin.launching.LaunchingHandler;
import com.massyframework.beanskin.runtime.framework.installing.strategy.DefaultAwaitStrategyRepository;
import com.massyframework.beanskin.runtime.framework.protocol.URLStreamHandlerFactoryUtils;
import com.massyframework.beanskin.service.ServiceRepositoryFactory;
import com.massyframework.beanskin.service.awaitstrategy.AwaitStrategyRepository;
import com.massyframework.beanskin.util.BeanSkinServiceLoaderUtils;
import com.massyframework.beanskin.util.classloading.ClassLoaderUtils;
import com.massyframework.beanskin.util.classloading.ResourceLocateFilterRepository;
import com.massyframework.beanskin.util.exceptioncollect.ExceptionCollectUtils;
import com.massyframework.beanskin.util.localstore.LocalStore;
import com.massyframework.beanskin.util.sorting.OrderComparator;

/**
 * 缺省的运行框架工厂
 * @author huangkh
 *
 */
public class DefaultFrameowrkFactory implements FrameworkFactory {

	private Logger logger = LoggerFactory.getLogger(DefaultFrameowrkFactory.class);
	/**
	 * 
	 */
	public DefaultFrameowrkFactory() {
		URLStreamHandlerFactoryUtils.initURLStreamHandlerFactory();
	}

	@Override
	public Framework createFramework(FrameworkConfig config) {
		ClassLoader selfLoader = this.getClass().getClassLoader();
		ClassLoader contextLoader = ClassLoaderUtils.setThreadContextClassLoader(selfLoader);
		try {	
			this.createCustomer(config);
			
			ModuleRepository moduleRepository = 
					BeanSkinServiceLoaderUtils.loadServiceWithThreadContext(ModuleRepository.class);
			this.initFrameworkConfig(config, moduleRepository);
			ServiceRepositoryFactory serviceRepositoryFactory =
					BeanSkinServiceLoaderUtils.loadServiceWithThreadContext(ServiceRepositoryFactory.class);
			if (serviceRepositoryFactory instanceof ModuleListener) {
				moduleRepository.addListener((ModuleListener)serviceRepositoryFactory);
			}
			if (serviceRepositoryFactory instanceof FrameworkListener) {
				config.addListener((FrameworkListener)serviceRepositoryFactory);
			}
			
			
			
			DefaultFramework.Builder builder =
					DefaultFramework.newBuilder();
			Framework result =
					builder.moduleRepository(moduleRepository)
						.serviceRepositoryFactory(serviceRepositoryFactory)
						.frameworkConfig(config)
						.build();
			return result;
		}finally {
			Thread.currentThread().setContextClassLoader(contextLoader);
		}
	}
	
	/**
	 * 创建客户
	 * @param config {@link Customer}
	 * @return {@link Customer}
	 */
	protected Customer createCustomer(FrameworkConfig config) {
		CustomerLoader loader = new CustomerLoader();
		LocalStore localStore = config.getBean(LocalStore.class.getName(), LocalStore.class);
		Customer result = loader.loadCustomer(localStore);
		config.defineExportService(Customer.class.getName(), result, builder -> {
			builder.addExportService(Customer.class)
				.topRanking();
		});
		return result;
	}
	
	protected ModuleRepository createModuleRepository(FrameworkConfig config) {
		ModuleRepository result = 
				BeanSkinServiceLoaderUtils.loadServiceWithThreadContext(ModuleRepository.class);
		if (config instanceof DefaultFrameworkConfig) {
			List<ModuleListener> list = ((DefaultFrameworkConfig)config).moduleListeners;
			for (ModuleListener listener: list) {
				result.addListener(listener);
			}
			list.clear();
		}
		
		return result;
	}
	
	/**
	 * 初始化Framework配置器
	 * @param config
	 * @param exceptons
	 */
	protected void initFrameworkConfig(FrameworkConfig config, ModuleRepository moduleRepo) {
		//添加资源定位过滤器资源库
		config.addBean(ResourceLocateFilterRepository.class.getName(), new DefaultResourceLocateFilterRepository());
		
		//添加模块资源库
		config.addBean(ModuleRepository.class.getName(), moduleRepo);
		
		//等待策勒资源库
		config.defineExportService(AwaitStrategyRepository.class.getName(), 
				new DefaultAwaitStrategyRepository(), builder->{
					builder.addExportService(AwaitStrategyRepository.class)
						.description("等待服务就绪策略资源库")
						.topRanking();
				});
		//执行服务线程池
		ExecutorService executorService = this.createExecutorService();
		config.defineExportService(ExecutorService.class.getName(), executorService, 
				builder -> {
					builder.addExportService(ExecutorService.class)
						.name("frameworkThread")
						.description("系统执行服务线程池")
						.topRanking();
				});
						
		List<LaunchingHandler> handlers = 
				BeanSkinServiceLoaderUtils.loadServies(LaunchingHandler.class,
						this.getClass().getClassLoader());
		Collections.sort(handlers, new OrderComparator<LaunchingHandler>());
		for (LaunchingHandler handler: handlers) {
			try {
				handler.init(config);
			}catch(Exception e) {
				ExceptionCollectUtils.addException(
						new ModuleRuntimeException(
								SimpleModuleIdentifier.createModuleIdentifierWithKernel(), e));
				if (logger.isErrorEnabled()) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		
		//清理所有模块监听器
		if (config instanceof DefaultFrameworkConfig) {
			List<ModuleListener> list = ((DefaultFrameworkConfig)config).moduleListeners;
			for (ModuleListener listener: list) {
				moduleRepo.addListener(listener);
			}
			list.clear();
		}
		
	}
	
	/**
	 * 创建执行服务
	 * @return {@link ExecutorService}
	 */
	protected ExecutorService createExecutorService() {
		//计算当前运行环境的cpu核心数，采用2倍做为内核
		int number = Runtime.getRuntime().availableProcessors();
		return Executors.newFixedThreadPool(number, new ThreadFactory(){
			
			private AtomicInteger count = new AtomicInteger(1);

			@Override
			public Thread newThread(Runnable r) {
				Thread result = new Thread(r);
				result.setName("frameworkTread-".concat(Integer.toString(count.incrementAndGet())));
				return result;
			}
		});
	}

}
